#include "wifi_my.h"
/* 定义WiFi名称和密码 */
#define MY_WIFI_SSID "esptest"
#define MY_WIFI_PASSWORD "12345671"

/* 宏定义WIFI连接事件标志位、连接失败标志位以及智能配网标志位 */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
#define ESPTOUCH_CONNECTED_BIT BIT2
#define ESPTOUCH_DONE_BIT BIT3

/* 函数声明区域 */
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
static void smartconfig_init_startion(void);
static void checkWifi(void);

/* 定义一个WIFI连接FreeRTOS事件标志组句柄 */
static EventGroupHandle_t wifi_event_group_handler;

/* WIFI连接入口函数 */
void wifi_init_sta()
{
    printf(">>>ESP_WIFI_MODE_STA START<<<\n");

    oled_show_wifi_connect();

    /* 创建一个FreeRTOS事件标志组 */
    wifi_event_group_handler = xEventGroupCreate();

    /* 初始化底层TCP/IP堆栈.应用程序启动时,应先调用此函数一次 */
    tcpip_adapter_init();

    // /* 设置静态ip */
    // tcpip_adapter_ip_info_t info;
    // IP4_ADDR(&info.ip, 192, 168, 0, 18);
    // IP4_ADDR(&info.gw, 192, 168, 0, 1);
    // IP4_ADDR(&info.netmask, 255, 255, 255, 0);
    // tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
    // tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &info);

    /* 创建默认事件循环 */
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* 使用WIFI_INIT_CONFIG_DEFAULT() 来获取一个默认的WIFI配置参数结构体 */
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    /* 根据cfg参数初始化wifi需要的资源 */
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    /* 将事件处理程序注册到系统默认事件循环,分别是WIFI事件和IP地址事件 */
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));

    /* 定义WIFI连接的ssid和password参数 */
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = MY_WIFI_SSID,
            .password = MY_WIFI_PASSWORD},
    };

    /* 设置WIFI的工作模式为STA */
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    /* 设置WIFI连接的参数,主要是SSID和PWD */
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    /* 启动WIFI连接 */
    ESP_ERROR_CHECK(esp_wifi_start());

    /* 检查WIFI连接状态(启动智能配网) */
    checkWifi();
    /* 注销并删除事件组 */
    ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
    ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
    ESP_ERROR_CHECK(esp_event_handler_unregister(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler));
    vEventGroupDelete(wifi_event_group_handler);
    printf(">>>wifi_init_sta finished<<< \n");
}

/* 检查WIFI链接状态函数 */
void checkWifi()
{
    /* 使用事件标志组等待连接建立(WIFI_CONNECTED_BIT)或连接失败(WIFI_FAIL_BIT)事件 */
    EventBits_t bits;                                              /* 定义一个事件位变量来接收事件标志组等待函数的返回值 */
    bits = xEventGroupWaitBits(wifi_event_group_handler,           /* 需要等待的事件标志组的句柄 */
                               WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, /* 需要等待的事件位 */
                               pdTRUE,                             /* 为pdFALSE时，在退出此函数之前所设置的这些事件位不变，为pdTRUE则清零*/
                               pdFALSE,                            /* 为pdFALSE时，设置的这些事件位任意一个置1就会返回，为pdTRUE则需全为1才返回 */
                               portMAX_DELAY);                     /* 设置为最长阻塞等待时间，单位为时钟节拍 */

    /* 根据事件标志组等待函数的返回值获取WiFi连接状态 */
    if (bits & WIFI_CONNECTED_BIT) /* WiFi连接成功事件 */
    {
        printf("connected to ap SSID:%s \n", MY_WIFI_SSID);
    }
    else if (bits & WIFI_FAIL_BIT) /* WiFi连接失败事件 */
    {
        printf("Failed to connect to SSID:%s \n", MY_WIFI_SSID);
        oled_show_connect_fail();
        smartconfig_init_startion(); /* 开启智能配网*/
    }
    else
    {
        printf("UNEXPECTED EVENT");  /* 没有等待到事件 */
        smartconfig_init_startion(); /* 开启智能配网*/
    }
}

/* 系统循环事件处理函数 */
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    /* WIFI重连次数 */
    static int retry_num = 0;
    /* 系统事件为WIFI事件 */
    if (event_base == WIFI_EVENT)
    {
        if (event_id == WIFI_EVENT_STA_START)
        {
            esp_wifi_connect();
        }
        else if (event_id == WIFI_EVENT_STA_DISCONNECTED)
        {
            /* 尝试次数 */
            if (retry_num < 5)
            {
                esp_wifi_connect();
                retry_num++;
                printf("retry to connect to the AP %d times. \n", retry_num);
                oled_show_reconnect(retry_num);
            }
            else
            {
                /* 将WIFI连接事件标志组的WIFI连接失败事件位置1 */
                xEventGroupSetBits(wifi_event_group_handler, WIFI_FAIL_BIT);
            }
        }
    }
    /* 系统事件为ip地址事件,但事件id为成功获取到的ip地址 */
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        printf("got ip: %s \n", ip4addr_ntoa(&event->ip_info.ip));

        char *s = ip4addr_ntoa(&event->ip_info.ip);

        // uart_write_bytes(uart_log_port, s, strlen(s));
        retry_num = 0;

        oled_show_wifi_connected();
        /* 将WIFI连接FreeRTOS事件标志组的WIFI连接成功事件位置1 */
        xEventGroupSetBits(wifi_event_group_handler, WIFI_CONNECTED_BIT);
    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE)
    {
        printf("scan done\n");
    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL)
    {
        printf("Found channel\n");
        oled_show_smartconfig_find();
    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD)
    {
        printf("Got SSID and password\n");

        smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
        wifi_config_t wifi_config;
        uint8_t ssid[33] = {0};
        uint8_t password[65] = {0};

        bzero(&wifi_config, sizeof(wifi_config_t));
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
        wifi_config.sta.bssid_set = evt->bssid_set;

        if (wifi_config.sta.bssid_set == true)
        {
            memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
        }

        memcpy(ssid, evt->ssid, sizeof(evt->ssid));
        memcpy(password, evt->password, sizeof(evt->password));
        printf("SSID:%s \n", ssid);
        oled_show_smartconfig_ssid((char *)ssid);
        printf("PASSWORD:%s \n", password);

        ESP_ERROR_CHECK(esp_wifi_disconnect());
        ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
        ESP_ERROR_CHECK(esp_wifi_connect());
        printf("Wifi reconnect over");
    }
    else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE)
    {
        xEventGroupSetBits(wifi_event_group_handler, ESPTOUCH_DONE_BIT);
    }
}

/* 智能配网初始函数 */
static void smartconfig_init_startion(void)
{
    printf(">>>Smart Config start<<< \n");
    /* 设置智能配网类型为AIRKISS */
    ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_AIRKISS));

    /* 开始智能配网，配置智能配网事件 */
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_smartconfig_start(&cfg));

    EventBits_t bits;
    while (1)
    {
        bits = xEventGroupWaitBits(wifi_event_group_handler, ESPTOUCH_CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, pdFALSE, portMAX_DELAY);

        if (bits & ESPTOUCH_CONNECTED_BIT)
        {
            printf("WIFI connected to ap \n");
            oled_show_wifi_connected();
        }

        if (bits & ESPTOUCH_DONE_BIT)
        {
            printf(">>>Smart Config over<<< \n");
            esp_smartconfig_stop();
            break;
        }
    }
}
